package com.wcs.exam.common.server.upload.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.obs.services.ObsClient;
import com.obs.services.model.*;
import com.wcs.exam.common.server.upload.Upload;
import com.wcs.exam.common.server.upload.UploadFace;
import com.wcs.exam.common.util.FileUtils;
import com.wcs.exam.common.util.ImgUtil;
import com.wcs.exam.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 华为云 OBS
 */
@Slf4j
@Component(value = "huawei")
public class HuaweiUploadImpl implements UploadFace {

    @Override
    public String uploadPic(MultipartFile file, Upload upload) {
        return putObject(file, upload, AccessControlList.REST_CANNED_PUBLIC_READ);
    }

    @Override
    public String uploadPicBase64(String imgBase64, Upload upload) {
        // 获取图片类型
        String type = ImgUtil.getBase64Type(imgBase64);
        if (StrUtil.isBlank(type)) {
            type = "jpg";
        }
        return uploadPicBase64(imgBase64, FileUtils.getFileName(type), upload);
    }

    @Override
    public String uploadPicBase64(String imgBase64, String fileName, Upload upload) {
        byte[] data = java.util.Base64.getDecoder().decode(imgBase64);
        //  创建字节数组输入流
        InputStream inputStream = new ByteArrayInputStream(data);
        // 上传文件
        return putObject(inputStream, fileName, upload, AccessControlList.REST_CANNED_PUBLIC_READ);
    }

    @Override
    public String uploadDoc(MultipartFile file, Upload upload, Boolean isPublicRead) {
        return putObject(file, upload, isPublicRead ? AccessControlList.REST_CANNED_PUBLIC_READ : AccessControlList.REST_CANNED_PRIVATE);

    }

    @Override
    public String uploadDoc(File file, String fileName, Upload upload, Boolean isPublicRead) {
        return putObject(file, fileName, upload, isPublicRead ? AccessControlList.REST_CANNED_PUBLIC_READ : AccessControlList.REST_CANNED_PRIVATE);

    }

    @Override
    public void delete(String fileUrl, Upload storageConfig) {
        try {
            String filePath = fileUrl.replace(storageConfig.getHuaWeiObsUrl(), "");
            ObsClient obsClient = getObsClient(storageConfig.getHuaWeiObsAccessKey(), storageConfig.getHuaWeiObsSecretKey(), storageConfig.getHuaWeiObsEndpoint(), storageConfig.getHuaWeiObsLocation(), storageConfig.getHuaWeiObsBucket());
            obsClient.deleteObject(storageConfig.getHuaWeiObsBucket(), filePath);
        } catch (Exception e) {
            log.error("删除失败", e);
        }
    }

    @Override
    public void delete(Collection<String> fileUrls, Upload upload) {

    }

    @Override
    public String getDownloadUrl(String docUrl, int expireSeconds, Upload storageConfig) {
        ObsClient obsClient = getObsClient(storageConfig.getHuaWeiObsAccessKey(), storageConfig.getHuaWeiObsSecretKey(), storageConfig.getHuaWeiObsEndpoint(), storageConfig.getHuaWeiObsLocation(), storageConfig.getHuaWeiObsBucket());
        TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, expireSeconds);
        request.setBucketName(storageConfig.getHuaWeiObsBucket());
        request.setObjectKey(docUrl.replace(storageConfig.getHuaWeiObsUrl(), ""));
        TemporarySignatureResponse response = obsClient.createTemporarySignature(request);
        return response.getSignedUrl();
    }

    @Override
    public String getPreviewConfig(String docUrl, int expireSeconds, Upload upload) {
        if (StringUtils.hasText(upload.getHuaWeiObsPreviewUrl())) {
            String previewUrl = FileUtils.getFilePath(upload.getHuaWeiObsPreviewUrl(), "onlinePreview?url=");
            Map<String, String> map = new HashMap<>();
            map.put("previewUrl", previewUrl + URLEncoder.encode(Base64.encode(getDownloadUrl(docUrl, expireSeconds, upload)), StandardCharsets.UTF_8));
            return JsonUtil.toJsonString(map);
        }
        return "";
    }

    private static String putObject(File file, String fileName, Upload upload, AccessControlList acl) {
        try (InputStream inputStream = new FileInputStream(file)) {
            return putObject(inputStream, fileName, upload, acl);
        } catch (Exception e) {
            log.error("上传失败", e);
            return "";
        }
    }

    private static String putObject(MultipartFile file, Upload upload, AccessControlList acl) {
        try (InputStream inputStream = file.getInputStream()) {
            String name = file.getOriginalFilename();
            return putObject(inputStream, name, upload, acl);
        } catch (Exception e) {
            log.error("上传失败", e);
            return "";
        }
    }

    /**
     * 上传文件
     */
    private static String putObject(InputStream inputStream, String fileName, Upload upload, AccessControlList acl) {
        try {
            String filePath = FileUtils.getFilePath(FileUtils.PREFIX, FileUtils.getFileName(fileName.substring(fileName.lastIndexOf(".") + 1)));
            ObsClient ossClient = getObsClient(upload.getHuaWeiObsAccessKey(), upload.getHuaWeiObsSecretKey(), upload.getHuaWeiObsEndpoint(), upload.getHuaWeiObsLocation(), upload.getHuaWeiObsBucket());
            ObjectMetadata meta = new ObjectMetadata();
            meta.setContentEncoding("UTF-8");
            meta.setContentDisposition("attachment;filename={}".replace("{}", URLEncoder.encode(fileName, StandardCharsets.UTF_8)));
            PutObjectRequest request = new PutObjectRequest();
            request.setBucketName(upload.getHuaWeiObsBucket());
            request.setObjectKey(filePath);
            request.setInput(inputStream);
            request.setMetadata(meta);
            request.setAcl(acl);
            ossClient.putObject(request);
            return FileUtils.getFilePath(upload.getHuaWeiObsUrl(), filePath);
        } catch (Exception e) {
            log.error("上传失败", e);
            return "";
        }
    }

    /**
     * 获取OBS客户端
     *
     * @param accessKey  访问Key
     * @param secretKey  秘钥Key
     * @param endPoint   终端节点
     * @param location   区域位置
     * @param bucketName 桶名称
     * @return OBS客户端
     */
    private static ObsClient getObsClient(String accessKey, String secretKey, String endPoint, String location, String bucketName) {
        // 创建ObsClient实例
        ObsClient obsClient = new ObsClient(accessKey, secretKey, endPoint);
        boolean existBucket = obsClient.headBucket(bucketName);
        if (!existBucket) {
            CreateBucketRequest request = new CreateBucketRequest();
            request.setBucketName(bucketName);
            // 设置桶访问权限为公共读，默认是私有读写
            request.setAcl(AccessControlList.REST_CANNED_PRIVATE);
            // 设置桶的存储类型为标准存储
            request.setBucketStorageClass(StorageClassEnum.STANDARD);
            // 设置桶区域位置
            request.setLocation(StrUtil.isNotBlank(location) ? location : "cn-east-3");
            // 创建桶成功
            obsClient.createBucket(request);
        }
        return obsClient;
    }
}
